package com.easipass.exangeservice.msg;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;

/**
 * 
 * @version $Id$
 * @author itea
 * @date 2010-2-11
 */
public class ByteArrayMsg extends AbstractMsg implements TextMsg {

	/** "ByteArrayMsg.ATTR_BYTE_ARRAY" */
	public static final String ATTR_BYTE_ARRAY = "ByteArrayMsg.ATTR_BYTE_ARRAY";
	
	public ByteArrayMsg() {}
	
	public ByteArrayMsg(Msg msg) {
		copyAttributesFrom(msg);
	}

	public ByteArrayMsg(String encoding) {
		setEncoding(encoding);
	}
	
	public ByteArrayMsg(byte[] bytes) {
		setByteArray(bytes);
	}
	
	public ByteArrayMsg(byte[] bytes, String encoding) {
		setByteArray(bytes);
		setEncoding(encoding);
	}
	
	public static ByteArrayMsg copyTextMsg(TextMsg msg) throws IOException {
		return copyRawMsg(msg);
	}
	
	public static ByteArrayMsg copyRawMsg(RawMsg msg) throws IOException {
		ByteArrayMsg m = new ByteArrayMsg();
		m.copyAttributesFrom(msg);
		copyRawData(msg, m, -1);
		return m;
	}
	
	public static ByteArrayMsg copyRawMsg(RawMsg msg, String encoding) throws IOException {
		ByteArrayMsg m = new ByteArrayMsg();
		m.copyAttributesFrom(msg);
		copyRawData(msg, m, -1);
		m.setEncoding(encoding);
		return m;
	}
	
	public InputStream openInputStream() {
		byte[] b = getByteArray();
		if(b == null) return null;
		ByteArrayInputStream in = new ByteArrayInputStream(b);
		return in;
	}

	private class MyOutputStream extends ByteArrayOutputStream {
		public MyOutputStream() {
			super(1024);
			copy2ATTR_BYTE_ARRAY();
		}

		@Override
		public synchronized void reset() {
			super.reset();
			copy2ATTR_BYTE_ARRAY();
		}

		@Override
		public synchronized void write(byte[] b, int off, int len) {
			super.write(b, off, len);
			copy2ATTR_BYTE_ARRAY();
		}

		@Override
		public synchronized void write(int b) {
			super.write(b);
			copy2ATTR_BYTE_ARRAY();
		}
		
		private void copy2ATTR_BYTE_ARRAY() {
			setAttribute(ATTR_BYTE_ARRAY, this.toByteArray());
		}
	}
	
	public OutputStream openOutputStream() {
		return new MyOutputStream();
	}

	public long getSize() {
		byte [] b = getAttribute(ATTR_BYTE_ARRAY);
		return b == null ? 0 : b.length;
	}
	
	public void setByteArray(byte[] b) {
		setAttribute(ATTR_BYTE_ARRAY, b);
	}
	
	public byte[] getByteArray() {
		return getAttribute(ATTR_BYTE_ARRAY);
	}

	public String getEncoding() {
		return getAttribute(ATTR_ENCODING);
	}

	public void setEncoding(String encoding) {
		setAttribute(ATTR_ENCODING, encoding);
	}
	
	public Reader openReader() throws IOException {
		InputStream in = openInputStream();
		if(in == null) return null;
		String encoding = getEncoding() == null ? "UTF-8" : getEncoding();
		Charset c = Charset.forName(encoding);
		return new InputStreamReader(in, c);
	}

	public Writer openWriter() throws IOException {
		OutputStream out = openOutputStream();
		if(out == null) return null;
		String encoding = getEncoding() == null ? "UTF-8" : getEncoding();
		Charset c = Charset.forName(encoding);
		return new OutputStreamWriter(out, c);
	}

}
